-module(bnode_repeater).
-include("btree.hrl").

%% API
-export([forward/2]).
-export([backward/2]).

forward(BTree, BNode) ->
    #bt{} = BTree,
    #bn{id = NodeID, props = Props, children = [ChildID], status = Status} = BNode,
    Loop = get_loop(Props),
    case is_integer(Loop) andalso not(maps:is_key(times, Status)) of
        true ->
            BNode2 = BNode#bn{status = #{times => Loop}},
            BTree2 = BTree#bt{nodes = maps:put(NodeID, BNode2, BTree#bt.nodes)},
            bnode_api:forward(BTree2, ChildID);
        false ->
            bnode_api:forward(BTree, ChildID)
    end.


backward(BTree, BNode) ->
    #bt{nodes = Nodes, result = Result} = BTree,
    #bn{id = NodeID, props = Props, status = Status} = BNode,
    Loop = get_loop(Props),
    if
        %% 直到xx类型成功返回
        (Loop == until_succ andalso Result == ?SUCCESS);
        (Loop == until_fail andalso Result == ?FAILURE) ->
            bnode_api:backward(BTree#bt{result = ?SUCCESS}, BNode);
        %% 直到xx类型未达成/永久循环返回
        Loop == until_succ;
        Loop == until_fail;
        Loop == infinity ->
            BTree#bt{result = BNode};
        %% 有限次数型返回
        true ->
            CurTimes = maps:get(times, Status),
            case CurTimes - 1 of
                0 ->
                    BNode2 = BNode#bn{status = #{}},
                    BTree2 = BTree#bt{nodes = maps:put(NodeID, BNode2, Nodes)},
                    bnode_api:backward(BTree2, BNode2);
                N ->
                    BNode2 = BNode#bn{status = #{times => N}},
                    BTree#bt{
                        result = BNode2,
                        nodes = maps:put(NodeID, BNode2, Nodes)
                    }
            end
    end.

%%%-----------------------------------------------------------------------------
%%% Internal Functions
%%%-----------------------------------------------------------------------------
get_loop(Props) ->
    proplists:get_value(loop, Props, infinity).